﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using AvalonDock;
using FxArchitect;
using Microsoft.Win32;

namespace EffectArchitect
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        [Flags]
        enum CmdKeys : byte
        {
            None = 0,
            LeftCtrl = 1 << 0,
            RightCtrl = 1 << 1,
            Ctrl = LeftCtrl | RightCtrl
        }
        CmdKeys cmdKeysDown = CmdKeys.None;

        /// <summary>
        /// Gets or sets the status displayed on the status bar.
        /// </summary>
        string Status 
        {
            get { return appStatus.Content as string; } 
            set { appStatus.Content = value; }
        }

        public MainWindow()
        {
            InitializeComponent();
            Status = EffectArchitectResources.DefaultStatus;
        }

        void OnShowDockableContents(object sender, RoutedEventArgs e)
        {
            DockableContent selectedContent = ((MenuItem)e.OriginalSource).DataContext as DockableContent;
            if (selectedContent != null)
            {
                if (selectedContent.State != DockableContentState.Docked &&
                    selectedContent.State != DockableContentState.FloatingWindow &&
                    selectedContent.State != DockableContentState.DockableWindow)
                    selectedContent.Show(DockManager);
                selectedContent.Activate();
            }
        }

        void DockManager_Loaded(object sender, RoutedEventArgs e)
        {
            if (File.Exists(EffectArchitectResources.LayoutFilename))
                DockManager.RestoreLayout(EffectArchitectResources.LayoutFilename);
        }
        void DockManager_ActiveDocumentChanged(object sender, EventArgs e)
        {
            FxInfo fxInfo = DockManager.ActiveDocument as FxInfo;
            if (fxInfo != null)
                fxInfo.ActivatePreview();
        }

        void ShowAboutWindow(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(EffectArchitectResources.AboutText, 
                            EffectArchitectResources.AboutCaption);
        }

        void OnSaveLayout(object sender, RoutedEventArgs e)
        {
            DateTime time = DateTime.Now;
            SaveFileDialog fileDialog = new SaveFileDialog();
            fileDialog.Filter = EffectArchitectResources.Filter_LayoutFiles;
            fileDialog.FileName = string.Format("FxArchitectLayout_{0}-{1}-{2}-{3}-{4}.fxelayout", 
                                                time.Year, time.Month, time.Day,
                                                time.Hour, time.Minute);
            if (fileDialog.ShowDialog() ?? false)
                DockManager.SaveLayout(fileDialog.FileName);
        }
        void OnLoadLayout(object sender, RoutedEventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Filter = EffectArchitectResources.Filter_LayoutFiles;
            if (fileDialog.ShowDialog() ?? false)
                DockManager.RestoreLayout(fileDialog.FileName);
        }

        void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            DockManager.SaveLayout(EffectArchitectResources.LayoutFilename);
            renderSurface.Game.Exit();
        }

        void OpenNewTextEditor(string filename)
        {
            FxInfo fxInfo = new FxInfo(renderSurface.Game, filename);

            fxInfo.RaiseError += (error) => { lvErrorsAndWarnings.Items.Add(error); };
            fxInfo.RemoveError += (error) => { lvErrorsAndWarnings.Items.Remove(error); };
            fxInfo.Closed += (sender, e) => { documents.Items.Remove(fxInfo); };
            fxInfo.Closing += (sender) => { tvEffectList.Items.Remove(fxInfo); };

            Dispatcher.BeginInvoke(new Action(() =>
            {
                documents.Items.Add(fxInfo);
                tvEffectList.Items.Add(fxInfo.TreeViewRoot);
                fxInfo.Show(DockManager);
                fxInfo.Activate();
            }), null);
        }

        void CreateNewEffect(object sender, RoutedEventArgs e)
        {
            OpenNewTextEditor(null);
        }
        void OpenExistingEffect(object sender, RoutedEventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Filter = EffectArchitectResources.Filter_FxFiles;
            if (fileDialog.ShowDialog() ?? false)
                OpenNewTextEditor(fileDialog.FileName);
        }
        void SaveCurrentEffect(object sender, RoutedEventArgs e)
        {
            FxInfo fxInfo = DockManager.ActiveDocument as FxInfo;
            if (fxInfo != null)
                fxInfo.SaveFiles(null, true);
        }
        void SaveCurrentEffectAs(object sender, RoutedEventArgs e)
        {
            FxInfo fxInfo = DockManager.ActiveDocument as FxInfo;
            if (fxInfo != null)
            {
                string filename = fxInfo.Title;
                SaveFileDialog fileDialog = new SaveFileDialog();
                fileDialog.Filter = EffectArchitectResources.Filter_FxFiles;
                if (fileDialog.ShowDialog() ?? false)
                    fxInfo.SaveFiles(fileDialog.FileName, true);
            }
        }

        void ToggleWordWrap(object sender, RoutedEventArgs e)
        {
            TextEditorSettings.Default.WordWrap = !TextEditorSettings.Default.WordWrap;
            TextEditorSettings.Default.Save();

            foreach (FxInfo fxInfo in DockManager.Documents)
            {
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    fxInfo.Editor.WordWrap = TextEditorSettings.Default.WordWrap;
                }), null);
            }
        }
        void ToggleLineNumbering(object sender, RoutedEventArgs e)
        {
            TextEditorSettings.Default.LineNumbers = !TextEditorSettings.Default.LineNumbers;
            TextEditorSettings.Default.Save();

            foreach (FxInfo fxInfo in DockManager.Documents)
            {
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    fxInfo.Editor.ShowLineNumbers = TextEditorSettings.Default.LineNumbers;
                }), null);
            }
        }

        void ExitProgram(object sender, RoutedEventArgs e) { Close(); }

        void GotoErrorLocation(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton != MouseButton.Left)
                return;

            XEffectErrorOrWarning error = lvErrorsAndWarnings.SelectedItem as XEffectErrorOrWarning;
            if (error != null)
            {
                FxInfo source = error.Source.GoToErrorLocation(error);
                if (source != null)
                {
                    source.Show(DockManager);
                    source.Activate();
                }
            }
        }

        void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.LeftCtrl)
                cmdKeysDown |= CmdKeys.LeftCtrl;
            else if (e.Key == Key.RightCtrl)
                cmdKeysDown |= CmdKeys.RightCtrl;
            else if (e.Key == Key.S)
            {
                if ((cmdKeysDown & CmdKeys.Ctrl) != CmdKeys.None)
                {
                    FxInfo fxInfo = DockManager.ActiveDocument as FxInfo;
                    if (fxInfo != null)
                    {
                        fxInfo.SaveFiles();
                        e.Handled = true;
                    }
                }
            }
        }

        void Window_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.LeftCtrl)
                cmdKeysDown &= ~CmdKeys.LeftCtrl;
            else if (e.Key == Key.RightCtrl)
                cmdKeysDown &= ~CmdKeys.RightCtrl;
        }
    }
}
